using SynoManager.Communication;
using System.Collections.Specialized;
using System.Collections;
using LitJson;
using System.Reflection;

namespace SynoManager.DownloadStation
{
    public sealed class DownloadStationClient : StationClientBase
    {
        private const int _downloadStationServiceID = 5;
        private const string _downloadStationServiceUrl = @"/download/downloadman.cgi";
        private const string _settingsServiceUrl = @"/download/btsetting.cgi";

        public DownloadStationClient(SynoDevice device)
            : base(device, _downloadStationServiceID, _downloadStationServiceUrl)
        {
        }

        #region ShareGet
        public ShareGetResult ShareGet()
        {
            return GetAction<ShareGetResult>("shareget");
        }

        public class ShareGetResult : ClientRequestResult
        {
            public string ShareName { get; set; }
        }
        #endregion

        #region GetAll
        ///download/downloadman.cgi?_dc=1226493889159&action=getall&start=0&limit=25&sort=task_id&dir=ASC
        public GetAllResult GetAll()
        {
            return GetAll(0, 100, "task_id", "ASC");
        }

        private GetAllResult GetAll(int start, int limit, string sort, string dir)
        {
            return GetAction<GetAllResult>("getall", "start={0}&limit={1}&sort={2}&dir={3}", start, limit, sort, dir);
        }

        public class GetAllResult : ClientRequestResult
        {
            public DownloadTaskInfo[] items;
            public int total;
            public string total_down;
            public string total_rate;
            public string total_up;
        }

        public class DownloadTaskInfo
        {
            public bool blEmptySize;
            public string current_rate;
            public string current_size;
            public string filename;
            public string progress;
            public string status;
            public int task_id;
            public string total_size;
            public string upload_rate;
            public string username;
        }
        #endregion

        #region GetOne
        public GetOneResult GetOne(int taskid)
        {
            return GetAction<GetOneResult>("getone", "taskid={0}", taskid);
        }

        public class GetOneResult : ClientRequestResult
        {
            public GetOneData data;
        }

        public class GetOneData
        {
            public string create_time;
            public string currpeer;
            public string currpieces;
            public string destination;
            public string filename;
            public string filesize;
            public int id;
            public bool isnzb;
            public bool istorrent;
            public string progress;
            public int seedelapsed;
            public string speed;
            public string start_time;
            public string status;
            public int timeleft;
            public string totalpeer;
            public string totalpieces;
            public string transfered;
            public string url;
            public string username;
            public string seeders_leechers; // don't know where this one is used!?
            public string seeding_interval;
        }
        #endregion

        #region GetFileList
        public GetFileListResult GetFileList(int taskid)
        {
            return GetAction<GetFileListResult>("getfilelist", "taskid={0}", taskid);            
        }

        public class GetFileListResult : ClientRequestResult
        {
            public DownloadTaskFileInfo[] items;
            public int total;
        }

        public class DownloadTaskFileInfo
        {
            public bool dl;
            public string name;
            public string size;
        }
        #endregion

        #region ApplyTask
        public ClientRequestResult ApplyTask(int taskid, ApplyTaskFileInfo[] files, int seedingInterval, int seedingRatio)
        {
            ApplyTaskInfo taskInfo = new ApplyTaskInfo();
            taskInfo.data = files;

            StringDictionary dict = new StringDictionary();
            dict.Add("taskid", taskid.ToString());
            dict.Add("fsel", JsonMapper.ToJson(taskInfo));
            dict.Add("seeding_interval", seedingInterval.ToString());
            dict.Add("seeding_ratio", seedingRatio.ToString());

            return PostAction<ClientRequestResult>("applytask", dict);
        }

        public class ApplyTaskInfo
        {
            public ApplyTaskFileInfo[] data;
        }

        public class ApplyTaskFileInfo
        {
            public string name;
            public bool dl;
        }
        #endregion

        #region BTSetting
        public DownloadStationConfigResult GetConfiguration()
        {
            return PostRequest<DownloadStationConfigResult>(_settingsServiceUrl, "action=load");
        }

        public DownloadStationConfigResult SaveConfiguration(DownloadStationConfigData config)
        {
            StringDictionary dictionary = new StringDictionary();
            dictionary.Add("action", "apply");

            foreach (FieldInfo fi in typeof(DownloadStationConfigData).GetFields())
            {
                object value = fi.GetValue(config);
                if (value == null)
                    value = "";

                dictionary.Add(fi.Name, value.ToString());
            }

            return PostRequest<DownloadStationConfigResult>(_settingsServiceUrl, dictionary);
        }

        public class DownloadStationConfigResult : ClientRequestResult
        {
            public DownloadStationConfigData data;
        }

        public class DownloadStationConfigData
        {
            public int btdhtport;
            public string btencrypt;
            public int btmaxpeers;
            public int dl_download_rate;
            public int dl_end_port;
            public int dl_max_tasks;
            public string dl_ordering;
            public string dl_port_type;
            public int dl_start_port;
            public int dl_upload_rate;
            public string dl_when_type;
            public string download_volume;
            public string download_volume_status;
            public int emule_tcp_port;
            public int emule_udp_port;
            public bool enablebtdht;
            public int enabledownload;
            public int from_hr;
            public int from_min;
            public bool ftpconn_enable;
            public int ftpmaxconn;
            public bool nzbauth;
            public int nzbnumconn;
            public string nzbpass;
            public string nzbpass2;
            public int nzbport;
            public string nzbserver;
            public string nzbuser;
            public int seeding_interval;
            public int seeding_ratio;
            public int to_hr;
            public int to_min;
            public int volume_count;
            public DownloadStationConfigVolumeInfo[] volume_list;
        }


        public class DownloadStationConfigVolumeInfo
        {
            public string display;
            public string value; // in beta 	DSM 2.0-0803 int -> string
        }
        #endregion
    }
}